/**
 * Copyright (c) 2009-2011, chunquedong(YangJiandong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 
 * History:
 *     2010-05-05  Jed Young  Creation
 */
package chunmap.model.elem;

import chunmap.model.coord.Position;

/**
 * @author chunquedong
 * 
 */
public class Angle {
	private final Position p1;
	private final Position p2;
	private final Position p3;

	/**
	 * @param p1
	 * @param p2
	 * @param p3
	 */
	public Angle(Position p1, Position p2, Position p3) {
		this.p1 = p1;
		this.p2 = p2;
		this.p3 = p3;
	}

	public Position getP1() {
		return p1;
	}

	public Position getP2() {
		return p2;
	}

	public Position getP3() {
		return p3;
	}

	/**
	 * 计算三点之间的夹角,顺时针或共线时为正，逆时针为负,异常时返回0
	 */
	public double computeAngle() {
		double a = F2(p1.getX(), p2.getX(), p3.getX(), p1.getY(), p2.getY(), p3
				.getY());

		if (clockwise() >= 0) {
			return a;
		} else {
			return -a;
		}
	}

	/**
	 * 顺时针1,逆时针-1,共线0
	 */
	public int clockwise() {
		Vector v1 = new Vector(p2, p1);
		Vector v2 = new Vector(p2, p3);
		double d = v1.get2DCrossProduct(v2);

		if (d > 0)// 顺时针
			return -1;
		else if (d == 0)// 共线
			return 0;
		else
			// 逆时针
			return 1;
	}

	// *************************************************************
	// |
	// | 下面的函数来自C#版的chunmap
	// | 作者chunquedong @2009.5
	// |
	// *************************************************************

	// #region 辅助函数

	// ------------------------------------------------------------
	// / <summary>
	// / 两点之间的距离
	// / </summary>
	// / <param name="x1"></param>
	// / <param name="x2"></param>
	// / <param name="y1"></param>
	// / <param name="y2"></param>
	// / <returns></returns>
	private double F1(double x1, double x2, double y1, double y2) {
		double d1 = Math.pow((x1 - x2), 2.0);
		double d2 = Math.pow((y1 - y2), 2.0);
		double d = Math.sqrt(d1 + d2);
		return d;
	}

	// / <summary>
	// / A_2.0，三点之间的夹角，
	// / </summary>
	// / <param name="x1"></param>
	// / <param name="x2"></param>
	// / <param name="x3"></param>
	// / <param name="y1"></param>
	// / <param name="y2"></param>
	// / <param name="y3"></param>
	// / <returns>单位弧度</returns>
	private double F2(double x1, double x2, double x3, double y1, double y2,
			double y3) {
		double FenZi = F201(x1, x2, x3, y1, y2, y3);
		double FenMu = F202(x1, x2, x3, y1, y2, y3);

		if (FenMu == 0)
			return 0;

		double b = FenZi / FenMu;
		if (Math.abs(b) > 1)
			return 0;

		double a = Math.acos(b);
		return a;

	}

	// #region 计算夹角的辅助函数
	private double F201(double x1, double x2, double x3, double y1, double y2,
			double y3) {
		double r1 = F2011(x1, x2, x3);
		double r2 = F2011(y1, y2, y3);
		return r1 + r2;
	}

	private double F2011(double a1, double a2, double a3) {
		return (a1 - a2) * (a3 - a2);
	}

	private double F202(double x1, double x2, double x3, double y1, double y2,
			double y3) {
		double r1 = F1(x1, x2, y1, y2);
		double r2 = F1(x3, x2, y3, y2);
		return r1 * r2;
	}
	// #endregion
	// ------------------------------------------------------------
	// #endregion
}